package com.guit.hrms.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.guit.hrms.dto.approval.ApprovalOfferDTO;
import com.guit.hrms.dto.approval.ApprovalPlanDTO;
import com.guit.hrms.dto.interview.UpdateInterviewStatusDTO;
import com.guit.hrms.dto.wx.WxMessageDTO;
import com.guit.hrms.event.OfferCreatedEvent;
import com.guit.hrms.mapper.*;
import com.guit.hrms.po.Employee;
import com.guit.hrms.po.ToEmail;
import com.guit.hrms.po.Transaction;
import com.guit.hrms.po.approval.Approval;
import com.guit.hrms.po.approval.Depts;
import com.guit.hrms.po.approval.Position;
import com.guit.hrms.po.interview.Interviewee;
import com.guit.hrms.po.interview.Offer;
import com.guit.hrms.po.interview.Onboarding;
import com.guit.hrms.po.utilsPO.PageBean;
import com.guit.hrms.service.ApprovalService;
import com.guit.hrms.utils.*;
import com.guit.hrms.vo.ApprovalOfferVO;
import com.guit.hrms.vo.TransactionVO;
import com.guit.hrms.websocket.MessageWebSocketHandler;
import com.guit.hrms.wechat.service.WeChatService;
import jakarta.mail.MessagingException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@Service
public class ApprovalServiceImpl implements ApprovalService {
    @Autowired
    private ApprovalMapper approvalMapper;
    @Autowired
    private IntervieweeMapper intervieweeMapper;
    @Autowired
    private EmailUtil emailUtil;
    @Autowired
    private DepartmentMapper departmentMapper;
    @Autowired
    private AcademyMapper academyMapper;
    @Autowired
    private PositionMapper positionMapper;
    @Autowired
    private QueryMapper queryMapper;
    @Autowired
    private UpdateMapper updateMapper;
    @Autowired
    private RecruitmentMapper recruitmentMapper;
    @Autowired
    private OtherDeptMapper otherDeptMapper;
    @Autowired
    private EmpResumeMapper empResumeMapper;
    @Autowired
    private OnboardingMapper onboardingMapper;
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    @Autowired
    private WeChatService weChatService;
    @Autowired
    private AttendanceMapper attendanceMapper;

    /**
     * 获取请假记录
     *
     * @param page           当前页
     * @param pageSize       当前页面展示的数据条数
     * @param deptId         部门id
     * @param type           请假类型
     * @param approvalStatus 审批状态
     * @param revokeStatus   销假状态
     * @return 请假记录
     */
    @Override
    public PageBean queryLeaveRecords(Integer page, Integer pageSize, Integer deptId, Integer type, Integer approvalStatus, Integer revokeStatus, Integer extensionStatus) {
        PageHelper.startPage(page, pageSize);
        List<TransactionVO> records = approvalMapper.queryLeaveRecords(deptId, type, approvalStatus, revokeStatus, extensionStatus);
        Page<TransactionVO> p = (Page<TransactionVO>) records;
        return new PageBean(p.getTotal(), p.getResult());
    }

    /**
     * 审批请假
     * @param transaction 审批信息
     * @return 审批结果
     */
    @Override
    public Integer approvingLeave(Transaction transaction) {
        Integer result = approvalMapper.approvingLeave(transaction);
        WxMessageDTO wxMessageDTO = new WxMessageDTO();
        if (result == 1) {
            Map<String, Object> map = ThreadLocalUtil.get();
            String username = map.get("username").toString();
            Transaction transaction1 = attendanceMapper.getTransactionById3(transaction.getId());
            Employee employee = queryMapper.getById(transaction1.getEmployeeId());
            if (employee == null){
                throw new RuntimeException("员工不存在");
            }
            String openId = employee.getOpenId();

            boolean flag = false;
            wxMessageDTO.setThings("请假审批");
            wxMessageDTO.setTime(LocalDateTime.now());
            wxMessageDTO.setApprover(username);
            Map<String, Object> data = null;
            switch (transaction1.getType()) {
                case 1:
                    wxMessageDTO.setType("请假");
                    break;
                case 2:
                    wxMessageDTO.setType("出差");
                    break;
                case 3:
                    wxMessageDTO.setType("培训");
                    break;
            }
            if (transaction.getApprovalStatus() != null) {
                if (transaction.getApprovalStatus() == 2) {
                    wxMessageDTO.setResult("审批通过");
                    MessageWebSocketHandler.sendToUser(employee.getEmployeeId(), "您的"+ wxMessageDTO.getType() +"申请已通过");
                } else if (transaction.getApprovalStatus() == 3) {
                    wxMessageDTO.setResult("驳回申请");
                    MessageWebSocketHandler.sendToUser(employee.getEmployeeId(), "您的"+ wxMessageDTO.getType() +"申请已被驳回");
                } else {
                    return 1;
                }
                if (openId == null || openId.isEmpty()) {
                    return 1;
                }
                try {
                    openId = AESUtil.decrypt(openId);
                } catch (Exception e) {
                    throw new RuntimeException("openId解密失败");
                }
                data = WeChatMsgUtil.buildMsg(wxMessageDTO);
                flag = weChatService.sendSubscribeMessage(openId, data);
                if (!flag) {
                    log.error("微信消息发送失败");
                }
                return 1;
            } else if (transaction.getExtensionStatus() != null) {
                if (transaction.getExtensionStatus() == 2) {
                    wxMessageDTO.setResult("同意延期");
                    MessageWebSocketHandler.sendToUser(employee.getEmployeeId(), "您的"+ wxMessageDTO.getType() +"的延期申请已被同意");
                } else if (transaction.getExtensionStatus() == 3) {
                    wxMessageDTO.setResult("延期驳回");
                    MessageWebSocketHandler.sendToUser(employee.getEmployeeId(), "您的"+ wxMessageDTO.getType() +"的延期申请已被驳回");
                } else {
                    return 1;
                }
                if (openId == null || openId.isEmpty()) {
                    return 1;
                }
                try {
                    openId = AESUtil.decrypt(openId);
                } catch (Exception e) {
                    throw new RuntimeException("openId解密失败");
                }
                data = WeChatMsgUtil.buildMsg(wxMessageDTO);
                flag = weChatService.sendSubscribeMessage(openId, data);
                if (!flag) {
                    log.error("微信消息发送失败");
                }
                return 1;
            }
            return 1;
        } else {
            return 0;
        }
    }

    /**
     * 获取招聘计划(分页)
     *
     * @param page     当前页
     * @param pageSize 页面记录大小
     * @param planType 计划类型
     * @return 招聘计划列表
     */
    @Override
    public PageBean getRecruitmentPlan(Integer page, Integer pageSize, Integer planType) {
        PageHelper.startPage(page, pageSize);
        List<Approval> approvalList = approvalMapper.getRecruitmentPlan(planType);

        if (planType != null) {
            String name = null;
            if (planType == 1) {
                for (Approval approval : approvalList) {
                    List<Depts> deptsList = approvalMapper.getAllDeptId(approval.getPlanId());
                    approval.setDepts(deptsList);
                    for (Depts dept : deptsList) {
                        name = departmentMapper.getDepartmentByDeptNumber(dept.getNumbering()).getDeptName();
                        List<Position> positions = approvalMapper.getPositioToDept(approval.getPlanId(), dept.getNumbering());
                        dept.setPositions(positions);
                        dept.setName(name);
                    }
                }
            } else if (planType == 2) {
                for (Approval approval : approvalList) {
                    List<Depts> deptsList = approvalMapper.getAllAcademyId(approval.getPlanId());
                    approval.setDepts(deptsList);
                    for (Depts dept : deptsList) {
                        name = academyMapper.getAcademyByDeptNumber(dept.getNumbering()).getAcademyName();
                        List<Position> positions = approvalMapper.getPositionToAcademy(approval.getPlanId(), dept.getNumbering());
                        dept.setPositions(positions);
                        dept.setName(name);
                    }
                }
            } else {
                for (Approval approval : approvalList) {
                    List<Depts> deptsList = approvalMapper.getAllDeptId(approval.getPlanId());
                    approval.setDepts(deptsList);
                    for (Depts dept : deptsList) {
                        //如果查询部门中间表有结果则将该结果填入
                        if (approval.getPlanType() == 1) {
                            List<Position> positionsToDept = approvalMapper.getPositioToDept(approval.getPlanId(), dept.getNumbering());
                            if (positionsToDept != null) {
                                dept.setPositions(positionsToDept);
                            }
                        } else if (approval.getPlanType() == 2) {
                            List<Position> positionsToAcademy = approvalMapper.getPositionToAcademy(approval.getPlanId(), dept.getNumbering());
                            if (positionsToAcademy != null) {
                                dept.setPositions(positionsToAcademy);
                            }
                        }
                    }
                }
            }
        } else {
            for (Approval approval : approvalList) {
                List<Depts> deptsList = new ArrayList<>();
                if (approval.getPlanType() == 1) {
                    deptsList = approvalMapper.getAllDeptId(approval.getPlanId());
                } else if (approval.getPlanType() == 2) {
                    deptsList = approvalMapper.getAllAcademyId(approval.getPlanId());
                } else {
                    continue;
                }
                String name = null;
                approval.setDepts(deptsList);
                for (Depts dept : deptsList) {
                    //如果查询部门中间表有结果则将该结果填入
                    if (approval.getPlanType() == 1) {
                        name = departmentMapper.getDepartmentByDeptNumber(dept.getNumbering()).getDeptName();
                        List<Position> positionsToDept = approvalMapper.getPositioToDept(approval.getPlanId(), dept.getNumbering());
                        if (positionsToDept != null) {
                            dept.setPositions(positionsToDept);
                        }
                        dept.setName(name);
                    } else if (approval.getPlanType() == 2) {
                        name = academyMapper.getAcademyByDeptNumber(dept.getNumbering()).getAcademyName();
                        List<Position> positionsToAcademy = approvalMapper.getPositionToAcademy(approval.getPlanId(), dept.getNumbering());
                        if (positionsToAcademy != null) {
                            dept.setPositions(positionsToAcademy);
                        }
                        dept.setName(name);
                    }
                }
            }
        }

        Page<Approval> p = (Page<Approval>) approvalList;
        return new PageBean(p.getTotal(), p.getResult());
    }

    /**
     * 审批招聘计划（修改招聘计划的审批状态）
     * @param approvalPlanDTO 审批信息
     * @return 结果
     */
    @Override
    public Integer updateRecruitmentPlan(ApprovalPlanDTO approvalPlanDTO,String employeeId) {
        return approvalMapper.updateRecruitmentPlan(approvalPlanDTO,employeeId);
//        WxMessageDTO wxMessageDTO = new WxMessageDTO();
//        if (result == 1) {
//            Map<String, Object> map = ThreadLocalUtil.get();
//            String username = map.get("username").toString();
//            Recruitment recruitment = recruitmentMapper.getRecruitmentPlanByPlanId(approvalPlanDTO.getPlanId());
//            String openId = queryMapper.getById(recruitment.getCreatedBy()).getOpenId();
//            if (openId == null || openId.isEmpty()) {
//                return 1;
//            }
//            try {
//                openId = AESUtil.decrypt(openId);
//            } catch (Exception e) {
//                throw new RuntimeException(e);
//            }
//
//            boolean flag = false;
//            wxMessageDTO.setThings("招聘计划审批");
//            wxMessageDTO.setTime(LocalDateTime.now());
//            wxMessageDTO.setApprover(username);
//            if (recruitment.getPlanType() == 1) {
//                wxMessageDTO.setType("管理岗位");
//            } else if (recruitment.getPlanType() == 2) {
//                wxMessageDTO.setType("专任教师");
//            } else if (recruitment.getPlanType() == 3) {
//                wxMessageDTO.setType("其他岗位");
//            }
//            if (approvalPlanDTO.getApproveStatus() == 2) {
//                wxMessageDTO.setResult("审批通过");
//            } else if (approvalPlanDTO.getApproveStatus() == 3) {
//                wxMessageDTO.setResult("驳回申请");
//            } else {
//                return 1;
//            }
//            Map<String, Object> data = WeChatMsgUtil.buildMsg(wxMessageDTO);
//            flag = weChatService.sendSubscribeMessage(openId, data);
//            if (!flag) {
//                throw new RuntimeException("微信消息发送失败");
//            } else {
//                return 1;
//            }
//        } else {
//            return 0;
//        }
}

/**
 * 获取发offer申请(分页)
 * @param page     当前页
 * @param pageSize 页面记录大小
 * @param status   审批状态
 * @return 招聘计划列表
 */
@Override
public PageBean getApplyOfferMsg(Integer page, Integer pageSize, Integer status) {
    PageHelper.startPage(page, pageSize);
    List<ApprovalOfferVO> offerList = approvalMapper.getApplyOfferMsg(status);
    List<ApprovalOfferVO> approvalOfferVOList = new ArrayList<>();
    Interviewee interviewee = null;
    Employee employee = null;
    for (ApprovalOfferVO offer : offerList) {
        interviewee = intervieweeMapper.getIntervieweeById(offer.getIntervieweeId());
        offer.setIntervieweeName(interviewee != null ? interviewee.getName() : null);
        employee = queryMapper.getById(offer.getApplicantId());
        offer.setApplicantName(employee == null ? null : employee.getUsername());
        employee = queryMapper.getById(offer.getApproverId());
        offer.setApproverName(employee == null ? null : employee.getUsername());
        approvalOfferVOList.add(offer);
    }
    BeanUtils.copyProperties(approvalOfferVOList, offerList);
    Page<ApprovalOfferVO> p = (Page<ApprovalOfferVO>) offerList;
    return new PageBean(p.getTotal(), p.getResult());
}

//    /**
//     * 生成账号
//     * @return 账号信息
//     */
//    @Override
//    public CreateAccountVO createAccount() {
//        CreateAccountVO createAccountVO = new CreateAccountVO();
//        UpdateDTO updateDTO = new UpdateDTO();
//        String employeeId;
//        Integer result = 0;
//        do {
//            do {
//                StringBuilder sb = new StringBuilder();
//                for (int i = 0; i < 7; i++) {
//                    int digit = ThreadLocalRandom.current().nextInt(0, 10);
//                    sb.append(digit);
//                }
//                employeeId = sb.toString();
//            } while (queryMapper.getById(employeeId) != null);
//            updateDTO.setEmployeeId(employeeId);
//            updateDTO.setPassword(MD5Util.encrypt("123456"));
//            result = updateMapper.createNewAccount(updateDTO);
//        } while (result == 0);
//        updateDTO.setPassword("123456");
//        BeanUtils.copyProperties(updateDTO, createAccountVO);
//
//        return createAccountVO;
//    }

/**
 * 审批发offer申请
 * @param approvalOfferDTO 审批信息
 * @return 结果
 */
@Override
@Transactional
public Integer updateApplyOfferMsg(ApprovalOfferDTO approvalOfferDTO) {
    Map<String, Object> map = ThreadLocalUtil.get();
    String employeeId = map.get("employeeId").toString();
    String username = map.get("username").toString();
    String msg = null;
    Offer offer0 = intervieweeMapper.getOfferById(approvalOfferDTO.getId());
    if (offer0 == null) {
        throw new RuntimeException("offer不存在");
    }
    String openId = queryMapper.getById(offer0.getApplicantId()).getOpenId();

    Offer offer = new Offer();
    BeanUtils.copyProperties(approvalOfferDTO, offer);
    offer.setApproverId(employeeId);
    offer.setUpdateTime(LocalDateTime.now());

    // 获取应聘者信息
    Interviewee interviewee = intervieweeMapper.getIntervieweeById(offer0.getIntervieweeId());
    if (interviewee == null) {
        throw new RuntimeException("应聘者不存在");
    }

    WxMessageDTO wxMessageDTO = new WxMessageDTO();
    wxMessageDTO.setThings("发送offer审批");
    wxMessageDTO.setTime(LocalDateTime.now());
    wxMessageDTO.setApprover(username);
    wxMessageDTO.setType("offer");
    // 通过时的处理
    if (approvalOfferDTO.getStatus() == 1) {
        try {
            offer.setOfferFile(approvalOfferDTO.getOfferFile().getBytes());
            offer.setSendTime(LocalDateTime.now());

            // 生成token
            String token = UUID.randomUUID().toString();
            Map<String, Object> claims = new HashMap<>();
            claims.put("intervieweeId", interviewee.getId());
            claims.put("offerToken", token);
            token = JwtUtil.generateOfferToken(claims, approvalOfferDTO.getExpiryTime());
            offer.setOfferToken(token);
//            System.out.println("token:  " + token);

            // 更新面试状态
            UpdateInterviewStatusDTO updateInterviewStatusDTO = new UpdateInterviewStatusDTO();
            List<Integer> intervieweeIds = new ArrayList<>();
            intervieweeIds.add(interviewee.getId());
            updateInterviewStatusDTO.setIntervieweeIds(intervieweeIds);
            updateInterviewStatusDTO.setInterviewStatus(4);
            Integer result = intervieweeMapper.updateInterviewStatus(updateInterviewStatusDTO);
            if (result == 0) {
                throw new RuntimeException("更新应聘者面试状态失败");
            }

            // 创建入职信息
            Onboarding onboarding = new Onboarding();
            onboarding.setOfferId(offer.getId());
            onboarding.setIntervieweeId(interviewee.getId());
            onboarding.setOnboardingTime(approvalOfferDTO.getOnboardingTime());
            onboarding.setOnboardingPlace(approvalOfferDTO.getOnboardingPlace());
            onboarding.setStatus(0);
            onboarding.setUpdateTime(LocalDateTime.now());
            onboarding.setUpdateBy(employeeId);
            result = onboardingMapper.insertOnboarding(onboarding);
            if (result == 0) {
                throw new RuntimeException("新增待入职信息失败");
            }

            // 发送通过邮件
            List<String> emails = new ArrayList<>();
            emails.add(interviewee.getEmail());
            ToEmail toEmail = new ToEmail();
            toEmail.setTos(emails.toArray(new String[0]));
            toEmail.setSubject("offer通知");
            toEmail.setContent(approvalOfferDTO.getContent());
            toEmail.setOffer(approvalOfferDTO.getOfferFile());
            try {
                emailUtil.sendAttachmentMail(toEmail, token);
            } catch (MessagingException e) {
                throw new RuntimeException("邮件发送失败：", e);
            }
            eventPublisher.publishEvent(new OfferCreatedEvent(this, offer));
        } catch (IOException e) {
            throw new RuntimeException("处理offer文件时出错", e);
        }
        wxMessageDTO.setResult("审批通过");
        msg = "您申请发送的offer已通过";
    } else if (approvalOfferDTO.getStatus() == 2) {
        // 拒绝时发送拒绝邮件
        List<String> emails = new ArrayList<>();
        emails.add(interviewee.getEmail());
        ToEmail toEmail = new ToEmail();
        toEmail.setTos(emails.toArray(new String[0]));
        toEmail.setSubject("应聘不通过通知");
        toEmail.setContent("很抱歉，您不符合我校的招聘要求......");
        emailUtil.sendSimpleEmail(toEmail);
        wxMessageDTO.setResult("审批驳回");
        msg = "您申请发送的offer已被驳回";
    }

    // 更新offer状态
    Integer result = approvalMapper.updateApplyOfferMsg(offer);
    if (result == 0) {
        throw new RuntimeException("审批offer申请失败");
    }
    MessageWebSocketHandler.sendToUser(offer0.getApplicantId(), msg);
    if (openId == null || openId.isEmpty()) {
        return 1;
    }
    try {
        openId = AESUtil.decrypt(openId);
    } catch (Exception e) {
        throw new RuntimeException("openId解密失败");
    }
    Map<String, Object> data = WeChatMsgUtil.buildMsg(wxMessageDTO);
    boolean flag = weChatService.sendSubscribeMessage(openId, data);
    if (!flag) {
        log.error("微信消息发送失败");
    }
    return 1;
}

//    /**
//     * 获取销假记录
//     * @param page 当前页
//     * @param pageSize 当前页面展示的数据条数
//     * @param deptId 部门id
//     * @param type 请假类型
//     * @param revokeStatus 销假状态
//     * @return 销假记录
//     */
//    @Override
//    public PageBean queryCancelRecords(Integer page, Integer pageSize, Integer deptId, Integer type, Integer revokeStatus) {
//        PageHelper.startPage(page,pageSize);
//        List<TransactionVO> records = approvalMapper.queryLeaveRecords(deptId, type, 2, revokeStatus);
//        Page<TransactionVO> p =(Page<TransactionVO>) records;
//        return new PageBean(p.getTotal(),p.getResult());
//    }
//
//   /**
//    * 审批销假
//    * @param transaction 审批信息
//    * @return 结果
//    */
//   @Override
//   public Integer approvingCancel(Transaction transaction) {
//       transaction.setApprovalStatus(null);
//       transaction.setApprovalInstructions(null);
//       return approvalMapper.approvingLeave(transaction);
//   }
}
